//
//  BlockController.m
//  CommonProject
//
//  Created by 郝旭珊 on 2018/1/4.
//  Copyright © 2018年 郝旭珊. All rights reserved.
//

#import "BlockController.h"
#import "SecondController.h"

/*
 1. block 是 C 语言的,调用是c语言的myBlock(); 而不是oc的[self myBlock];
 2. Block 是一个数据类型
 
 **** block 的反向传值
 1.响应方: 准备块代码
 2.操作方: 执行块代码
 同:类似于协议方法的实现
 不同: 所有代码都在一处,并没有像代理一样分开

 ***** 代理
 1.被调用方(委托)
 1>定义协议
 2>定义代理
 3>在合适的时间通知代理执行方法
 
 2. 调用方(代理)
 1>遵守协议
 2>设置代理
 3>实现协议方法
 
 block优点: 简单
 如果回调方法在1~2个,用 block
 如果超过3个, 代码会显得臃肿
 */


#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width

@interface BlockController ()

@property (nonatomic, strong) UILabel *textLabel;


@end

@implementation BlockController

- (void)viewDidLoad {
    [super viewDidLoad];
    
//    //先判断 Block 是否执行了
//    if(self.passText){
//        self.passText(@"willpassText");
//    }
//
//    UILabel *textLabel = [[UILabel alloc]initWithFrame:CGRectMake((SCREEN_WIDTH-100)/2, 270, 100, 30)];
//    textLabel.backgroundColor = [UIColor orangeColor];
//    self.textLabel = textLabel;
//    [self.view addSubview:textLabel];
//
//    [self addEditView];
//
//    int c = 3;
//    int (^calculateSum)(int,int) = ^(int a,int b){
//        return a+b+c;
//    };
//    int sum = calculateSum(1,3);

}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    if (self.passSearchText){
        self.passSearchText(@"bejiing");
    }
}



- (void)dealloc{
    NSLog(@"BlockController 销毁了");
}


- (void)addEditView{
   
    EditView *editView = [[EditView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 200)];
    editView.backgroundColor = [UIColor lightGrayColor];
    editView.textChangeAction = ^(NSString *text) {
        self.textLabel.text = text;
    };
    [self.view addSubview:editView];
}


- (void)callBlock{
    
    //准备 block (调用他人的 block)
    SecondController *vc = [SecondController new];
    vc.secondControllerBlockName = ^(NSString *text) {
        NSLog(@"vc执行完了他的block");
    };
    
    //调用自己的 block 属性,传递自己的值
    self.blockControllerBlock(@"text");
    
    //调用带 block 参数的方法
    [self demoBlockWithCallBack:^(NSString *text) {
        NSLog(@"%@",text);
    }];
}

/*
 block 作为参数
 */
- (void)demoBlockWithCallBack:(void (^)(NSString *))callback{
    callback(@"string");
}



/*--------------c语言-------------------*/

- (void)demoBlock3{
    NSMutableString *strM  = [NSMutableString stringWithString:@"zhangsa"];
    NSLog(@"定义前%@,地址%p",strM,&strM);
    //string 用的是 copy
    
    void (^myBlock)() = ^{
        //setString 只是改变的指针指向地址的内容
        [strM setString:@"lili"];
        //这句话是修改的指针, 这句话是会报错的
        //        strM = [NSMutableString stringWithString:@"wangw"];
        
        NSLog(@"in block%@,地址%p",strM,&strM);
    };
    NSLog(@"定义后%@,地址%p",strM,&strM);
    
//    myBlock();
    NSLog(@"%@",strM); //lili
    
}



-(void)demoBlock2{
    //使用__ block
    __block int x = 10;
    NSLog(@"定义前: %p",&x); //栈区的地址
    
    //定义 block 时, 如果引用了__ block, 外部变量的指针地址就会变成堆区的地址,所以能改了
    void (^myBlock)()= ^{
        x = 80;
        NSLog(@"in block: %p",&x); //堆区的地址
        
    };
    
    myBlock();
    NSLog(@"%d",x); //80
    NSLog(@"定义后: %p",&x); //堆区的地址
    
}


void demoBlock1(){
    int x = 10;
    
    NSLog(@"定义前: %p",&x); //栈区的地址
    //定义 block 时, 引用外部变量时,会对外部变量的值做一个 copy
    //后续再改变变量的值, 不会影响 block 内部的值
    //不允许block 内部修改外部变量的值, 因为会破坏代码的可读性, 不易于维护
    //各管个的, 才不乱
    void (^myBlock1)() = ^{
        //        x = 80;
        NSLog(@"%d",x);
        NSLog(@"in block%p",&x);//堆区的地址
    };
    x = 20;
    myBlock1();
    NSLog(@"定义后%p",&x); //栈区的地址
    
}


void blockDefine(){
    /*
     block 定义的速记符号 "inlineblock"
     <#returnType#>(^blockName)(<#parameterTypes#>) = ^(<#parameters#>) {
     <#statements#>
     };
     */
    
    /*
     特点:
     1.类型比普通函数多了一个^
     2.设置数值, 有一个^
     3.定义时把 block 当成数据类型(因为=), 执行时当成函数
     */
    
    void(^blockName)() = ^{
        NSLog(@"myBlock");
    };
    
    
    blockName();
    
    //带参数 block
    void (^sumBlock)(int,int) = ^(int x,int y){
        
    };
    
    sumBlock(2,3);
    
    //带返回值block
    int (^sumBlock2)(int,int) = ^int(int a,int b){
        return a+b;
    };
    
    sumBlock2(3,6);
}


@end


@interface EditView()
@property (nonatomic, strong) UITextField *tf;
@end

@implementation EditView

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]){
        UITextField *tf = [[UITextField alloc]initWithFrame:CGRectMake(0, 64, SCREEN_WIDTH, 30)];
        tf.backgroundColor = [UIColor whiteColor];
        self.tf = tf;
        UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((SCREEN_WIDTH -80)/2, 100 , 100, 40)];
        btn.backgroundColor = [UIColor orangeColor];
        [btn setTitle:@"完成" forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
        
        [self addSubview:tf];
        [self addSubview:btn];
    }
    
    return self;
}


- (void)btnClick{
    if (self.textChangeAction){
        self.textChangeAction(self.tf.text);
    }
}

@end
